package com.java.reflection;

import com.java.reflection.test.Child;
import com.java.reflection.test.InterfaceA;

/**
 * 获取Class实例的三种方式 Class常用API
 */
public class ClassAPI {
    private class Inner {}
    
    // 获取Class实例的三种方式
    public static void getClassIns() throws ClassNotFoundException {
        // Class.forName("类的全路径")
        Class<?> child1 = Class.forName("com.java.reflection.test.Child");
        
        // 类名.class
        Class<Child> child2 = Child.class;
        
        // 对象名.getClass()
        Class<? extends Child> child3 = new Child().getClass();
    }
    
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
        // forName：获取Class实例
        Class<?> childCls = Class.forName("com.java.reflection.test.Child");
        
        // getName：获取全限定类名，常用于forName的参数，作为正确的全限定类名
        System.out.println(childCls.getName()); // com.java.reflection.test.Child
        
        // getCanonicalName：获取全限定类名，常用于日志或打印，作为便于阅读的全限定类名
        System.out.println(childCls.getCanonicalName()); // com.java.reflection.test.Child
        
        // 大部分情况下getName和getCanonicalName获取的全限定类名相同，但内部类或数组等不同
        System.out.println(Inner.class.getName()); // com.java.reflection.ClassIns$Inner
        System.out.println(Inner.class.getCanonicalName()); // com.java.reflection.ClassIns.Inner
        System.out.println(args.getClass().getName()); // [Ljava.lang.String;
        System.out.println(args.getClass().getCanonicalName()); // java.lang.String[]
        
        // getSimpleName：获取非全限定类名
        System.out.println(childCls.getSimpleName()); // Child
        
        // isInterface：判断Class实例表示的类是否为接口
        System.out.println(childCls.isInterface()); // false
        System.out.println(InterfaceA.class.isInterface()); // true
        
        // getInterfaces：获取Class实例表示的类实现的所有接口
        ReflectionUtil.println(childCls.getInterfaces()); // InterfaceA InterfaceB
        
        // getSupercalss：获取Class实例表示的类继承的所有直接父类
        System.out.println(childCls.getSuperclass()); // class com.java.reflection.test.Parent
        
        // newInstance：实例化Class实例表示的类，该类必须拥有无参构造
        System.out.println(childCls.newInstance()); // com.java.reflection.test.Child@1b6d3586
        
        // getConstructors：获取Class实例表示的类的所有public构造函数
        ReflectionUtil.println(childCls.getConstructors()); // public com.java.reflection.test.Child(java.lang.String,java.lang.String) public com.java.reflection.test.Child()
        
        // getConstructor：获取Class实例表示的类的指定参数的public构造函数
        System.out.println(childCls.getConstructor(String.class, String.class)); // public com.java.reflection.test.Child(java.lang.String,java.lang.String)
        
        // getDeclaredConstructors：获取Class实例表示的类的所有构造函数
        ReflectionUtil.println(childCls.getDeclaredConstructors()); // public com.java.reflection.test.Child(java.lang.String,java.lang.String) private com.java.reflection.test.Child(java.lang.String) public com.java.reflection.test.Child()
        
        // getDeclaredConstructor：获取Class实例表示的类的指定参数的构造函数
        System.out.println(childCls.getDeclaredConstructor(String.class)); // private com.java.reflection.test.Child(java.lang.String)
        System.out.println(childCls.getDeclaredConstructor(String.class, String.class)); // public com.java.reflection.test.Child(java.lang.String,java.lang.String)
        
        // getFields：获取Class实例表示的类的所有public成员属性，包括继承的public成员属性
        ReflectionUtil.println(childCls.getFields()); // childPublicVar parentPublicVar grandPublicVar
        
        // getField：获取Class实例表示的类的指定参数的public成员属性，包括继承的public成员属性
        System.out.println(childCls.getField("childPublicVar")); // public java.lang.String com.java.reflection.test.Child.childPublicVar
        System.out.println(childCls.getField("parentPublicVar")); // public java.lang.String com.java.reflection.test.Parent.parentPublicVar
        
        // getDeclaredFields：获取Class实例表示的类的所有成员属性，不包括继承的成员属性
        ReflectionUtil.println(childCls.getDeclaredFields()); // childPrivateVar childPublicVar
        
        // getDeclaredField：获取Class实例表示的类的指定参数的成员属性，不包括继承的成员属性
        System.out.println(childCls.getDeclaredField("childPrivateVar")); // private java.lang.String com.java.reflection.test.Child.childPrivateVar
        System.out.println(childCls.getDeclaredField("childPublicVar")); // public java.lang.String com.java.reflection.test.Child.childPublicVar
        
        // getMethods：获取Class实例表示的类的所有public成员方法，包括继承的public成员方法
        ReflectionUtil.println(childCls.getMethods()); // childPublicFunc parentPublicFunc grandPublicFunc ...(Object中继承的)
        
        // getMethod：获取Class实例表示的类的指定参数的public成员方法，包括继承的public成员方法
        System.out.println(childCls.getMethod("childPublicFunc", String.class)); // public void com.java.reflection.test.Child.childPublicFunc(java.lang.String)
        System.out.println(childCls.getMethod("parentPublicFunc")); // public void com.java.reflection.test.Parent.parentPublicFunc()
        
        // getDeclaredMethods：获取Class实例表示的类的所有成员方法，不包括继承的成员方法
        ReflectionUtil.println(childCls.getDeclaredMethods()); // childPrivateFunc childPublicFunc
        
        // getDeclaredMethod：获取Class实例表示的类的指定参数的成员方法，不包括继承的成员方法
        System.out.println(childCls.getDeclaredMethod("childPrivateFunc")); // private void com.java.reflection.test.Child.childPrivateFunc()
        System.out.println(childCls.getDeclaredMethod("childPublicFunc", String.class)); // public void com.java.reflection.test.Child.childPublicFunc(java.lang.String)
    }
}
